<html>
<head>
	<title> System Management & Security </title>
	<link rel="stylesheet" type="text/css" href="css/html.css">
	<link rel="stylesheet" type="text/css" href="css/docbook.css">
	<link rel="stylesheet" type="text/css" href="css/syntax.css">
	<link rel="stylesheet" type="text/css" href="css/regular_table.css">
</head>


<body>
<h1> 8 Shell Programming </h1>

<div class="TOC">
<dl>
	<dt><b>Table of Contents</b></dt>
	<dt>8.1 <a href="chapter8.html#PROG">     Shell Programming   </a></dt>
    <dt>8.2 <a href="chapter8.html#VARIABLES"> Variables          </a></dt>
    <dt>8.3 <a href="chapter8.html#CTRLSTRUCT">Control Structures </a></dt>
    <dt>8.4 <a href="chapter8.html#CTRLOP">    Control Operators  </a></dt>
    <dt>8.5 <a href="chapter8.html#CTRLOP">    The test command   </a></dt>
</dl>
</div>


<!------------------ 8.1 Shell Programming---------------------------------------->
<div class="SECT1">
<h1 class="SECT1"><a id="PROG" name="PROG">8.1 Shell Programming</a></h1>
<p>
As mentioned before, the shell provides a interprative language which enables you to  
write scripts for interactive or non-interactive use. You can write a shell script
simply by invoking arbitrary commands, programs and shell scripts. You can build
a sequence of calls and control it with an adequate control structure. Each call
returns a return value which informs you about the success of its operation. The
return value 0 means usually, that all was fine whereas a value unlike 0 inidicates the opposite.
Usually it is possible to get informations about the error in its manual page.
</p>

<div class="CODELISTING">
<pre>
$ ping 111.111.111.111
PING 111.111.111.111 (111.111.111.111) 56(84) bytes of data.
^C
--- 111.111.111.111 ping statistics ---
11 packets transmitted, 0 received, 100% packet loss, time 10001ms

$ echo $? # get the return value of the last call
1
$ man ping
....
RETURN VALUES
     The ping utility returns an exit status of zero if at least one response
     was heard from the specified host; a status of two if the transmission
     was successful but no responses were received; or another value (from
     &lt;sysexits.h&gt;) if an error occurred.
...
</pre>
</div>

<p>
Note that it is very important to check the return value as often as possible:
</p>

<div class="CODELISTING">
<pre>
# bad example:
cp -r my_very_important_data $HOME/a_safe_place
echo I am not sure but it should have worked...
rm -r my_very_important_data
echo Successful: surprise

# better example:
if $(cp -r my_very_important_data $HOME/a_safe_place)
then
	echo my_very_important_data has been saved successfully
	rm -r my_very_important_data	
else
	echo my_very_important_data has NOT been saved successfully 
fi
</pre>
</div>
</div>

<!------------------ 8.2 Variables ---------------------------------------->
<div class="SECT2">
<h1 class="SECT2"><a id="VARIABLES" name="VARIABLES">8.2 Variables</a></h1>
<p>
In the shell, all variables are strings and may occasionally be interpreted as
integer. Additionaly the shell provides a set of predefined variables:
</p>
<ul>
    <li>command line arguments in <b>$0, $1, ... $9</b></li>
    <li>number of command line arguments in <b>$#</b></li>
    <li>all parameters as one string in <b>$*</b>
    <li>all parameters as separates strings in <b>$@</b></li>
    <li>return value of the last command in <b>$?</b></li>
    <li>own PID in <b>$$</b></li>
</ul>

<p>
The following script shows the effects of the predefined shell variables:
</p>

<div class="CODELISTING">
<pre>
#------------------------------------------------------------------------------------------
# Shows the effects of the predefined shell variables
#
# Call: var_test arg1 arg2 ...arg9
#
# author:  Benjamin Friedrich
# version: 1.0  01.04.2009
#------------------------------------------------------------------------------------------

if [ $# -lt 1 ]
then
  echo Come on, I need at least one argument!
  exit 1
fi

echo name of this script \(\$\0\): $0
echo PID \(\$\$\): $$
echo number of given arguments \(\$\#\): $#

echo all arguments \(\$\*\): $*
echo all arguments \(\$\@\): $@

echo

echo loop over \(\"\$\*\"\):
for arg in "$*"
do
  echo $arg
done

echo

echo loop over \(\"\$\@\"\):
for arg in "$@"
do
  echo $arg
done

exit 0
</pre>
</div>

<p>Now let&rsquo;s look at the call result: </p>

<div class="CODELISTING">
<pre>
$ var_test
Come on, I need at least one argument!
$ echo $?
1

$ var_test 1 2 3
name of this script ($0): ./var_test
PID ($$): 10241
number of given arguments ($#): 3
all arguments ($*): 1 2 3
all arguments ($@): 1 2 3

loop over ("$*"):
1 2 3

loop over ("$@"):
1
2
3
$ echo $?
0
</pre>
</div>

<p>
Of course it is possible to set own variables such as <kbd class="USERINPUT">
myvar=value</kbd>. Note that there are no spaces in the assignment.
</p>

<div class="CODELISTING">
<pre>
$ myvar='Yeah! My own var!'
$ echo $myvar
Yeah! My own var!

$ # This assignment is wrong:
$ myvar2 = 'wrong'
</pre>
</div>
</div>

<!------------------ 8.3 Control Structures ---------------------------------------->
<div class="SECT3">
<h1 class="SECT3"><a id="CTRLSTRUCT" name="CTRLSTRUCT">8.3 Control Structures</a></h1>
<p>
As in every programming language, there are several control structures in the shell.
But the logic of the condition of a control structure is a litte different from
other programming languages. In the shell, there is always a command in the condition
such as
</p>

<div class="CODELISTING">
<pre>
if ls -l
then
   echo successful call of ls
fi

# But there is also a command in the condition:
if [ $# -lt 1 ] # this is the same as &quot;if test $# -lt 1&quot;
then
  echo Come on, I need at least one argument!
  exit 1
fi
</pre>
</div>

<p> 
So the shell takes the exit values of the called commands in the condition and uses
this for its condition evaluation. <b>Note that in the shell 0 means true and 1 means
false</b>.
</p>

<p>
In the listings below, you can see the available control structures in the shell:
</p>

<p><b>for...do...done</b><p>
<div class="CODELISTING">
<pre>
This kind of a for-loop is a little confusing because it is also looks like
there is no command in the condition. But actually here are 3 <kbd class="USERINPUT">expr</kbd> commands
(<a href="http://www.freebsd.org/cgi/man.cgi?query=expr&apropos=0&sektion=0&manpath=FreeBSD+7.0-RELEASE&format=html">expr manual page </a>).

for ((  i = 0 ;  i <= 100;  i++  ))
do
  mkdir /home/user$i
done
</pre>
</div>


<p><b>for...in...do...done</b><p>
<div class="CODELISTING">
<pre>
for var in one two three four
do
  echo $var
done
</pre>
</div>

<p><b>while...do...done</b><p>
<div class="CODELISTING">
<pre>
while sleep 100
do
  rm /tmp/*
done
</pre>
</div>

<p><b>until...do...done</b><p>
<div class="CODELISTING">
<pre>
until [ $(ls -l /tmp | wc -l) -gt 100 ]
do
  echo directory tmp is not too full
  sleep 100
done
</pre>
</div>

<p><b>if...then...[elif]...else...fi</b><p>
<div class="CODELISTING">
<pre>
if [ $(ls -l /tmp | wc -l) -le 100 ]
then
   echo have an eye on your tmp directory
elif [ $(ls -l /tmp | wc -l) -gt 100 ]
   echo sorry, but now I clean up your tmp directory
   rm /tmp/*
else
  echo ok I give up
  shutdown -P 0
fi
</pre>
</div>

<p><b>case...esac</b><p>
<div class="CODELISTING">
<pre>
case $car in
BMW)           echo Z3;
               echo Z4;
               echo Z8;
               ; # break
Mercedes)      echo C220;
               echo E320;
               echo SLK;
               ; # break
Toyota|Nissan) echo "don't like this car";
               ; # break
*) # default
               echo "don't know this car";
               ;
esac
</pre>
</div>

<p><b>other forms of control structures</b><p>
<div class="CODELISTING">
<pre>
If you want to express your control structure in an another form as listed
above you must use ";" as delimiter. For example

You can write ...

if [ 1 ]
then
  echo example
fi

...as

if [ 1 ]; then
 echo example
fi

...or as

if [ 1 ]; then echo example; fi

</pre>
</div>


</div>

<!------------------ 8.4 Control Operators ---------------------------------------->
<div class="SECT4">
<h1 class="SECT4"><a id="CTRLOP" name="CTRLOP">8.4 Control Operators</a></h1>

<p><b>command1 &amp;&amp; command2</b><p>
<p>command2 is executed only if commmand1 returns true</p>

<p><b>command1 || command2</b><p>
<p>command2 is executed only if commmand1 returns false</p>


<div class="CODELISTING">
<pre>
$ mkdir my_music_bak  &amp;&amp; cp &tilde;/music my_music_bak  &amp;&amp; tar czvf my_music_bak.tar.gz my_music_bak

You can also use control operators in conditions of control structures:


if mkdir my_music_bak  &amp;&amp; cp &tilde;/music my_music_bak  &amp;&amp; tar czvf my_music_bak.tar.gz my_music_bak
then
 echo built backup successfully
fi

Of course you can do the same with the test command within a condition:

if [ $number -lt 1 ] || [ $number -gt 1 ]
the
  echo number not equal 1
fi

</pre>
</div>

</div>


<!------------------ 8.5 The test command ---------------------------------------->
<div class="SECT5">
<h1 class="SECT5"><a id="TEST" name="TEST">8.5 The test command</a></h1>
<p>
The test command has been already used in the previous sections of this chapter.
It evaluates the given which you need to express according to the rules
in the appropriate manual page. There are two forms you can use to apply the test command:

<div class="CODELISTING">
<pre>
     test expression
     [ expression ]
</pre>
</div>

<p>
The table below shows the mostly needed conditions:
</p>

<table border="1">
    <thead>
        <tr>
            <th>call</th>
            <th>description</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>test -e file</td>
            <td>file exists</td>
        </tr>
        <tr>
            <td>test -r file</td>
            <td>file exists and is readable</td>
        </tr>
        <tr>
            <td>test -w file</td>
            <td>file exists and is writable</td>
        </tr>
        <tr>
            <td>test -x file</td>
            <td>file exists and is executable</td>
        </tr>
        <tr>
            <td>test -d file</td>
            <td>file exists and is a directory</td>
        </tr>
        <tr>
            <td>test -s file</td>
            <td>file exists and has a size greater than zero</td>
        </tr>
        <tr>
            <td>test STRING1 = STRING2</td>
            <td>the strings are equal</td>
        </tr>
        <tr>
            <td>test STRING1 != STRING2</td>
            <td>the strings are not equals</td>
        </tr>
        <tr>
            <td>test INTEGER1 -eq INTEGER"</td>
            <td>the integers are equals</td>
        </tr>
        <tr>
            <td>test INTEGER1 -ne INTEGER2</td>
            <td>the integers are not equal</td>
        </tr>
        <tr>
            <td>test INTEGER1 -ge INTEGER2</td>
            <td>INTEGER1 is greater than or equal to INTEGER2</td>
        </tr>
        <tr>
            <td>test INTEGER1 -gt INTEGER2</td>
            <td>INTEGER1 is greater than INTEGER2</td>
        </tr>
        <tr>
            <td>test INTEGER1 -le INTEGER2</td>
            <td>INTEGER1 is lower than or equal to INTEGER2</td>
        </tr>
        <tr>
            <td>test INTEGER1 -lt INTEGER2</td>
            <td>INTEGER1 is lower than INTEGER2</td>
        </tr>
    </tbody>
</table>

</p>
</div>

</body>
</html>